package com.lanou3g.ptp.wx.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.lanou3g.ptp.vo.AccessToken;
import com.lanou3g.ptp.vo.TemplateData;
import com.lanou3g.ptp.vo.WxResult;
import com.lanou3g.ptp.vo.WxTmplMsg;
import com.lanou3g.ptp.wx.service.WxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service(timeout = 10000)
public class WxServiceImpl implements WxService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RestTemplate restTemplate;
    @Value("" +
            "${ptp.redis.key.wx-tmpl-msg-code.prefix}")
    private String WX_TMPL_MSG_CODE_PREFIX;
    @Value("${ptp.redis.key.wx-tmpl-msg-code.expire}")
    private Long WX_TMPL_MSG_CODE_EXPIRE;
    @Value("${ptp.wx.appid}")
    private String appid;
    @Value("${ptp.wx.secret}")
    private String secret;
    @Value("${ptp.redis.key.wx-access-token}")
    private String WX_ACCESS_TOKEN_KEY;
    @Value("${ptp.wx.tmpl.sign}")
    private String WX_TMPL_SIGN;
    @Value("${ptp.wx.tmpl.diary}")
    private String WX_TMPL_DIARY;
    @Value("${ptp.wx.tmpl.approval}")
    private String WX_TMPL_APPROVAL;

    @Value("${ptp.wx.tmpl.report}")
    private String WX_TMPL_REPORT;
    @Value("${ptp.wx.tmpl.summary}")
    private String WX_TMPL_SUMMARY;

    // openid: oXyjq0JlN4dE_USJLhnG6Kn0YdJA
    // appid: wx239bb5fc057c051c
    // secret: ced52e74170d751e37a26b1585641cc0


    @Override
    public String getOpenId(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code&appid="
                + appid + "&secret=" + secret + "&js_code=" + code;
        String json = restTemplate.getForObject(url, String.class);
        WxResult result = JSON.parseObject(json, WxResult.class);
        if (result != null && result.getErrcode() == null) {
            return result.getOpenid();
        } else {
            return null;
        }
    }

    @Override
    public void storeCode(String openId, String code) {
        String key = WX_TMPL_MSG_CODE_PREFIX + openId + "-" + code;
        redisTemplate.opsForValue().set(key, code, WX_TMPL_MSG_CODE_EXPIRE, TimeUnit.DAYS);
    }

    private String getCode(String openId) {
        String pattern = WX_TMPL_MSG_CODE_PREFIX + openId + "-*";
        Set<String> keys = redisTemplate.keys(pattern);
        String code = null;
        if (keys != null && !keys.isEmpty()) {
            String key = keys.iterator().next();
            code = redisTemplate.opsForValue().get(key);
            redisTemplate.delete(key);
        }
        return code;
    }

    @Override
    public int checkCodeNum(String openId) {
        String pattern = WX_TMPL_MSG_CODE_PREFIX + openId + "-";
        Set<String> keys = redisTemplate.keys(pattern);
        return keys != null ? keys.size() : 0;
    }

    private boolean sendMessage(WxTmplMsg wxTmplMsg) {
        String accessToken = getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + accessToken;

        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        HttpEntity<WxTmplMsg> httpEntity = new HttpEntity<>(wxTmplMsg, headers);
        String json = restTemplate.postForObject(url, httpEntity, String.class);
        if (json != null) {
            WxResult msgResult = JSON.parseObject(json, WxResult.class);
            Integer errcode = msgResult.getErrcode();
            if (errcode.equals(41028) || errcode.equals(41029)) {
                String formId = getCode(wxTmplMsg.getTouser());
                if (formId == null) {
                    return false;
                }
                wxTmplMsg.setForm_id(formId);
                sendMessage(wxTmplMsg);
            } else {
                return errcode.equals(0);
            }
        }
        return false;
    }

    @Override
    public boolean sendMessage(String openId, int type, Map<String, TemplateData> data) {
        WxTmplMsg msg = new WxTmplMsg();
        msg.setTouser(openId);
        String formId = getCode(openId);
        if (formId == null) {
            return false;
        }
        msg.setForm_id(formId);
        msg.setData(data);
        if (type == WxTmplMsg.TYPE_SIGN) {
            msg.setTemplate_id(WX_TMPL_SIGN);
            msg.setPage("sign");
        }
        if (type == WxTmplMsg.TYPE_DIARY) {
            msg.setTemplate_id(WX_TMPL_DIARY);
            msg.setPage("diary");
        }
        if (type == WxTmplMsg.TYPE_TEMP_SIGN) {
            msg.setTemplate_id(WX_TMPL_SIGN);
            msg.setPage("temp-sign");
        }
        if (type == WxTmplMsg.TYPE_APPROVAL) {
            msg.setTemplate_id(WX_TMPL_APPROVAL);
            msg.setPage("sign");
        }

        if (type == WxTmplMsg.TYPE_REPORT) {
            msg.setTemplate_id(WX_TMPL_REPORT);
            msg.setPage("report");
        }
        if (type == WxTmplMsg.TYPE_SUMMARY) {
            msg.setTemplate_id(WX_TMPL_SUMMARY);
            msg.setPage("summary");
        }
        return sendMessage(msg);
    }

    private String getAccessToken() {
        String accessTokenString = redisTemplate.opsForValue().get(WX_ACCESS_TOKEN_KEY);
        if (accessTokenString == null) {
            //获取access_token
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
                    + appid + "&secret=" + secret;
            String json = restTemplate.getForObject(url, String.class);
            AccessToken accessToken = JSON.parseObject(json, AccessToken.class);
            accessTokenString = accessToken.getAccess_token();
            int expire = accessToken.getExpires_in() - 60 * 2;
            redisTemplate.opsForValue().set(WX_ACCESS_TOKEN_KEY, accessTokenString, expire, TimeUnit.SECONDS);
        }
        return accessTokenString;
    }
}
